package cn.ly.core.concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreTest extends Thread{
	
	Semaphore position;
	private int id;
	public SemaphoreTest(int i,Semaphore s){
		this.id = i;
		this.position = s;
	}
	
	public void run(){
		try{
			if(position.availablePermits() > 0){//查看可用信号是否大于0
				System.out.println("[" + id + "]#顾客进入厕所，有空位");
			}else{
				System.out.println("[" + id + "]#顾客进入厕所，没有空位，排队");
			}
			position.acquire();                   //试图获得一个许可，如果没有则阻塞
			System.out.println("[" + id + "]#顾客获得坑位");
			System.out.println("[" + id + "]#顾客正在使用中...");
			Thread.sleep((int)(Math.random()*10000));
			System.out.println("[" + id + "]#顾客使用完毕");
			position.release();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) throws Exception{
		ExecutorService list = Executors.newCachedThreadPool();
		Semaphore position = new Semaphore(2);
		for(int i=0; i<5; i++){
			list.submit(new SemaphoreTest(i,position));
		}
	    /*Thread.sleep((int)(Math.random()*10000));
	    System.out.println("清洁工等待顾客使用完毕...");
	    Thread.sleep((int)(Math.random()*10000));
		position.acquireUninterruptibly(2);
	    System.out.println("厕所暂停使用，清洁工正在清扫厕所中...");
	    Thread.sleep((int)(Math.random()*10000));
	    position.release(2);
	    System.out.println("使用完毕，需要清扫了");*/
		
		
		list.shutdown();
	}
	
	/**
	 * 此SynchronousQueue队列不能保证任务的绝对执行顺序，因为线程的启动顺序和执行顺序不确定。
	 * 实际上多线成是不能保证任务的执行顺序的，只能大体上保证时间顺序，先来得任务先被线程取走处理
	 * 如果要保证任务的绝对顺序，只能使用单线程
	 */
	
	 /**
	  * 一个计数信号量。从概念上讲，信号量维护了一个许可集合。如有必要，在许可可用前会阻塞每一个 acquire()，
	  * 然后再获取该许可。每个 release() 添加一个许可，从而可能释放一个正在阻塞的获取者。
	  * 但是，不使用实际的许可对象，Semaphore 只对可用许可的号码进行计数，并采取相应的行动。
	  */

}
